package org.ziroom.common.workflow.anno.importer.activiti;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.persistence.entity.integration.IntegrationContextManager;
import org.activiti.engine.integration.IntegrationContextService;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.activiti.spring.SpringAsyncExecutor;
import org.activiti.spring.SpringCallerRunsRejectedJobsHandler;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.SpringRejectedJobsHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * Provides sane definitions for the various beans required to be productive
 * with Activiti in Spring.
 *
 */
@SuppressWarnings("deprecation")
public abstract class AbstractProcessEngineAutoConfiguration extends AbstractProcessEngineConfiguration {

	private static final String THREAD_NAME = "activiti-task";
	private static final String PGATE_THREAD_NAME = "activiti-pgate-task";

	/**并行网关异步线程池
	 * @return
	 */
	@Bean
	public SpringAsyncExecutor springAsyncExecutor() {
		TaskExecutor applicationTaskExecutor = createPool(THREAD_NAME, 4, 8, 5000, 100);
		return new SpringAsyncExecutor(applicationTaskExecutor, springRejectedJobsHandler());
	}

	/**普通异步调度线程池
	 * @return
	 */
	@Bean
	public SpringAsyncExecutor springAsyncPGateExecutor() {
		TaskExecutor applicationTaskExecutor = createPool(PGATE_THREAD_NAME, 4, 8, 5000, 100);
		return new SpringAsyncExecutor(applicationTaskExecutor, springRejectedJobsHandler());
	}

	private AsyncTaskExecutor createPool(String threadName, int corePoolSize, int maxPoolSize, int keepAliveSeconds, int queueCapacity) {
		ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
		taskExecutor.setCorePoolSize(corePoolSize);//线程池维护线程的最少数量
		taskExecutor.setMaxPoolSize(maxPoolSize);//线程池维护线程的最大数量
		taskExecutor.setQueueCapacity(queueCapacity);//线程池所使用的缓冲队列
		taskExecutor.setKeepAliveSeconds(keepAliveSeconds);
		taskExecutor.setThreadFactory(new NamingThreadFactory(threadName));
		taskExecutor.initialize();
		return taskExecutor;
	}

	@Bean
	public SpringRejectedJobsHandler springRejectedJobsHandler() {
		return new SpringCallerRunsRejectedJobsHandler();
	}

	protected Set<Class<?>> getCustomMybatisMapperClasses(List<String> customMyBatisMappers) {
		Set<Class<?>> mybatisMappers = new HashSet<>();
		for (String customMybatisMapperClassName : customMyBatisMappers) {
			try {
				Class<?> customMybatisClass = Class.forName(customMybatisMapperClassName);
				mybatisMappers.add(customMybatisClass);
			} catch (ClassNotFoundException e) {
				throw new IllegalArgumentException("Class " + customMybatisMapperClassName + " has not been found.", e);
			}
		}
		return mybatisMappers;
	}

	@Bean
	public ProcessEngineFactoryBean processEngine(SpringProcessEngineConfiguration configuration) {
		return super.springProcessEngineBean(configuration);
	}

	@Bean
	@Override
	public RuntimeService runtimeServiceBean(ProcessEngine processEngine) {
		return super.runtimeServiceBean(processEngine);
	}

	@Bean
	@Override
	public RepositoryService repositoryServiceBean(ProcessEngine processEngine) {
		return super.repositoryServiceBean(processEngine);
	}

	@Bean
	@Override
	public TaskService taskServiceBean(ProcessEngine processEngine) {
		return super.taskServiceBean(processEngine);
	}

	@Bean
	@Override
	public HistoryService historyServiceBean(ProcessEngine processEngine) {
		return super.historyServiceBean(processEngine);
	}

	@Bean
	@Override
	public ManagementService managementServiceBeanBean(ProcessEngine processEngine) {
		return super.managementServiceBeanBean(processEngine);
	}

	@Bean
	public TaskExecutor taskExecutor() {
		return new SimpleAsyncTaskExecutor();
	}

	@Bean
	@Override
	public IntegrationContextManager integrationContextManagerBean(ProcessEngine processEngine) {
		return super.integrationContextManagerBean(processEngine);
	}

	@Bean
	@Override
	public IntegrationContextService integrationContextServiceBean(ProcessEngine processEngine) {
		return super.integrationContextServiceBean(processEngine);
	}

}
